/*

   Copyright 2001,2003  The Apache Software Foundation 

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package org.apache.batik.ext.awt.image.codec.tiff;


class TIFFFaxDecoder {

    private int bitPointer, bytePointer;
    private byte[] data;
    private int w, h;
    private int fillOrder;

    // Data structures needed to store changing elements for the previous
    // and the current scanline
    private int changingElemSize = 0;
    private int prevChangingElems[];
    private int currChangingElems[];

    // Element at which to start search in getNextChangingElement
    private int lastChangingElement = 0;

    private int compression = 2;

    // Variables set by T4Options
    private int uncompressedMode = 0;
    private int fillBits = 0;
    private int oneD;

    static int table1[] = {
	0x00, // 0 bits are left in first byte - SHOULD NOT HAPPEN
	0x01, // 1 bits are left in first byte
	0x03, // 2 bits are left in first byte
	0x07, // 3 bits are left in first byte
	0x0f, // 4 bits are left in first byte
	0x1f, // 5 bits are left in first byte
	0x3f, // 6 bits are left in first byte
	0x7f, // 7 bits are left in first byte
	0xff  // 8 bits are left in first byte
    };
    
    static int table2[] = {
	0x00, // 0
	0x80, // 1
	0xc0, // 2
	0xe0, // 3
	0xf0, // 4
	0xf8, // 5
	0xfc, // 6
	0xfe, // 7
	0xff  // 8
    };

    // Table to be used when fillOrder = 2, for flipping bytes.
    static byte flipTable[] = {
	 0,  -128,    64,   -64,    32,   -96,    96,   -32, 
	16,  -112,    80,   -48,    48,   -80,   112,   -16, 
	 8,  -120,    72,   -56,    40,   -88,   104,   -24, 
	24,  -104,    88,   -40,    56,   -72,   120,    -8, 
	 4,  -124,    68,   -60,    36,   -92,   100,   -28, 
	20,  -108,    84,   -44,    52,   -76,   116,   -12, 
	12,  -116,    76,   -52,    44,   -84,   108,   -20, 
	28,  -100,    92,   -36,    60,   -68,   124,    -4, 
	 2,  -126,    66,   -62,    34,   -94,    98,   -30, 
	18,  -110,    82,   -46,    50,   -78,   114,   -14, 
	10,  -118,    74,   -54,    42,   -86,   106,   -22, 
	26,  -102,    90,   -38,    58,   -70,   122,    -6, 
	 6,  -122,    70,   -58,    38,   -90,   102,   -26, 
	22,  -106,    86,   -42,    54,   -74,   118,   -10, 
	14,  -114,    78,   -50,    46,   -82,   110,   -18, 
	30,   -98,    94,   -34,    62,   -66,   126,    -2, 
	 1,  -127,    65,   -63,    33,   -95,    97,   -31, 
	17,  -111,    81,   -47,    49,   -79,   113,   -15, 
	 9,  -119,    73,   -55,    41,   -87,   105,   -23, 
	25,  -103,    89,   -39,    57,   -71,   121,    -7, 
	 5,  -123,    69,   -59,    37,   -91,   101,   -27, 
	21,  -107,    85,   -43,    53,   -75,   117,   -11, 
	13,  -115,    77,   -51,    45,   -83,   109,   -19, 
	29,   -99,    93,   -35,    61,   -67,   125,    -3, 
	 3,  -125,    67,   -61,    35,   -93,    99,   -29, 
	19,  -109,    83,   -45,    51,   -77,   115,   -13, 
	11,  -117,    75,   -53,    43,   -85,   107,   -21, 
	27,  -101,    91,   -37,    59,   -69,   123,    -5, 
	 7,  -121,    71,   -57,    39,   -89,   103,   -25, 
	23,  -105,    87,   -41,    55,   -73,   119,    -9, 
	15,  -113,    79,   -49,    47,   -81,   111,   -17, 
	31,   -97,    95,   -33,    63,   -65,   127,    -1, 
    };
    
    // The main 10 bit white runs lookup table
    static short white[] = {
	// 0 - 7
	6430,   6400,   6400,   6400,   3225,   3225,   3225,   3225, 
	// 8 - 15
	944,    944,    944,    944,    976,    976,    976,    976, 
	// 16 - 23
	1456,   1456,   1456,   1456,   1488,   1488,   1488,   1488, 
	// 24 - 31
	718,    718,    718,    718,    718,    718,    718,    718, 
	// 32 - 39
	750,    750,    750,    750,    750,    750,    750,    750, 
	// 40 - 47
	1520,   1520,   1520,   1520,   1552,   1552,   1552,   1552, 
	// 48 - 55
	428,    428,    428,    428,    428,    428,    428,    428, 
	// 56 - 63
	428,    428,    428,    428,    428,    428,    428,    428, 
	// 64 - 71
	654,    654,    654,    654,    654,    654,    654,    654, 
	// 72 - 79
	1072,   1072,   1072,   1072,   1104,   1104,   1104,   1104, 
	// 80 - 87
	1136,   1136,   1136,   1136,   1168,   1168,   1168,   1168, 
	// 88 - 95
	1200,   1200,   1200,   1200,   1232,   1232,   1232,   1232, 
	// 96 - 103
	622,    622,    622,    622,    622,    622,    622,    622, 
	// 104 - 111
	1008,   1008,   1008,   1008,   1040,   1040,   1040,   1040, 
	// 112 - 119
	44,     44,     44,     44,     44,     44,     44,     44, 
	// 120 - 127
	44,     44,     44,     44,     44,     44,     44,     44, 
	// 128 - 135
	396,    396,    396,    396,    396,    396,    396,    396, 
	// 136 - 143
	396,    396,    396,    396,    396,    396,    396,    396, 
	// 144 - 151
	1712,   1712,   1712,   1712,   1744,   1744,   1744,   1744, 
	// 152 - 159
	846,    846,    846,    846,    846,    846,    846,    846, 
	// 160 - 167
	1264,   1264,   1264,   1264,   1296,   1296,   1296,   1296, 
	// 168 - 175
	1328,   1328,   1328,   1328,   1360,   1360,   1360,   1360, 
	// 176 - 183
	1392,   1392,   1392,   1392,   1424,   1424,   1424,   1424, 
	// 184 - 191
	686,    686,    686,    686,    686,    686,    686,    686, 
	// 192 - 199
	910,    910,    910,    910,    910,    910,    910,    910, 
	// 200 - 207
	1968,   1968,   1968,   1968,   2000,   2000,   2000,   2000, 
	// 208 - 215
	2032,   2032,   2032,   2032,     16,     16,     16,     16, 
	// 216 - 223
	10257,  10257,  10257,  10257,  12305,  12305,  12305,  12305, 
	// 224 - 231
	330,    330,    330,    330,    330,    330,    330,    330, 
	// 232 - 239
	330,    330,    330,    330,    330,    330,    330,    330, 
	// 240 - 247
	330,    330,    330,    330,    330,    330,    330,    330, 
	// 248 - 255
	330,    330,    330,    330,    330,    330,    330,    330, 
	// 256 - 263
	362,    362,    362,    362,    362,    362,    362,    362, 
	// 264 - 271
	362,    362,    362,    362,    362,    362,    362,    362, 
	// 272 - 279
	362,    362,    362,    362,    362,    362,    362,    362, 
	// 280 - 287
	362,    362,    362,    362,    362,    362,    362,    362, 
	// 288 - 295
	878,    878,    878,    878,    878,    878,    878,    878, 
	// 296 - 303
	1904,   1904,   1904,   1904,   1936,   1936,   1936,   1936, 
	// 304 - 311
        -18413, -18413, -16365, -16365, -14317, -14317, -10221, -10221, 
	// 312 - 319
	590,    590,    590,    590,    590,    590,    590,    590, 
	// 320 - 327
	782,    782,    782,    782,    782,    782,    782,    782, 
	// 328 - 335
	1584,   1584,   1584,   1584,   1616,   1616,   1616,   1616, 
	// 336 - 343
	1648,   1648,   1648,   1648,   1680,   1680,   1680,   1680, 
	// 344 - 351
	814,    814,    814,    814,    814,    814,    814,    814, 
	// 352 - 359
	1776,   1776,   1776,   1776,   1808,   1808,   1808,   1808, 
	// 360 - 367
	1840,   1840,   1840,   1840,   1872,   1872,   1872,   1872, 
	// 368 - 375
	6157,   6157,   6157,   6157,   6157,   6157,   6157,   6157, 
	// 376 - 383
	6157,   6157,   6157,   6157,   6157,   6157,   6157,   6157, 
	// 384 - 391
        -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, 
	// 392 - 399
        -12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, 
	// 400 - 407
	14353,  14353,  14353,  14353,  16401,  16401,  16401,  16401, 
	// 408 - 415
	22547,  22547,  24595,  24595,  20497,  20497,  20497,  20497, 
	// 416 - 423
	18449,  18449,  18449,  18449,  26643,  26643,  28691,  28691, 
	// 424 - 431
	30739,  30739, -32749, -32749, -30701, -30701, -28653, -28653, 
	// 432 - 439
        -26605, -26605, -24557, -24557, -22509, -22509, -20461, -20461, 
	// 440 - 447
	8207,   8207,   8207,   8207,   8207,   8207,   8207,   8207, 
	// 448 - 455
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 456 - 463
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 464 - 471
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 472 - 479
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 480 - 487
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 488 - 495
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 496 - 503
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 504 - 511
	72,     72,     72,     72,     72,     72,     72,     72, 
	// 512 - 519
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 520 - 527
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 528 - 535
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 536 - 543
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 544 - 551
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 552 - 559
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 560 - 567
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 568 - 575
	104,    104,    104,    104,    104,    104,    104,    104, 
	// 576 - 583
	4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107, 
	// 584 - 591
	4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107, 
	// 592 - 599
	4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107, 
	// 600 - 607
	4107,   4107,   4107,   4107,   4107,   4107,   4107,   4107, 
	// 608 - 615
	266,    266,    266,    266,    266,    266,    266,    266, 
	// 616 - 623
	266,    266,    266,    266,    266,    266,    266,    266, 
	// 624 - 631
	266,    266,    266,    266,    266,    266,    266,    266, 
	// 632 - 639
	266,    266,    266,    266,    266,    266,    266,    266, 
	// 640 - 647
	298,    298,    298,    298,    298,    298,    298,    298, 
	// 648 - 655
	298,    298,    298,    298,    298,    298,    298,    298, 
	// 656 - 663
	298,    298,    298,    298,    298,    298,    298,    298, 
	// 664 - 671
	298,    298,    298,    298,    298,    298,    298,    298, 
	// 672 - 679
	524,    524,    524,    524,    524,    524,    524,    524, 
	// 680 - 687
	524,    524,    524,    524,    524,    524,    524,    524, 
	// 688 - 695
	556,    556,    556,    556,    556,    556,    556,    556, 
	// 696 - 703
	556,    556,    556,    556,    556,    556,    556,    556, 
	// 704 - 711
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 712 - 719
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 720 - 727
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 728 - 735
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 736 - 743
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 744 - 751
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 752 - 759
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 760 - 767
	136,    136,    136,    136,    136,    136,    136,    136, 
	// 768 - 775
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 776 - 783
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 784 - 791
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 792 - 799
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 800 - 807
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 808 - 815
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 816 - 823
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 824 - 831
	168,    168,    168,    168,    168,    168,    168,    168, 
	// 832 - 839
	460,    460,    460,    460,    460,    460,    460,    460, 
	// 840 - 847
	460,    460,    460,    460,    460,    460,    460,    460, 
	// 848 - 855
	492,    492,    492,    492,    492,    492,    492,    492, 
	// 856 - 863
	492,    492,    492,    492,    492,    492,    492,    492, 
	// 864 - 871
	2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059, 
	// 872 - 879
	2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059, 
	// 880 - 887
	2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059, 
	// 888 - 895
	2059,   2059,   2059,   2059,   2059,   2059,   2059,   2059, 
	// 896 - 903
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 904 - 911
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 912 - 919
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 920 - 927
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 928 - 935
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 936 - 943
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 944 - 951
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 952 - 959
	200,    200,    200,    200,    200,    200,    200,    200, 
	// 960 - 967
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 968 - 975
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 976 - 983
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 984 - 991
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 992 - 999
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 1000 - 1007
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 1008 - 1015
	232,    232,    232,    232,    232,    232,    232,    232, 
	// 1016 - 1023
	232,    232,    232,    232,    232,    232,    232,    232, 
    };
	
    // Additional make up codes for both White and Black runs
    static short additionalMakeup[] = {
	28679,  28679,  31752,  (short)32777,  
	(short)33801,  (short)34825,  (short)35849,  (short)36873,
	(short)29703,  (short)29703,  (short)30727,  (short)30727, 
	(short)37897,  (short)38921,  (short)39945,  (short)40969
    };

    // Initial black run look up table, uses the first 4 bits of a code
    static short initBlack[] = {
	// 0 - 7
	3226,  6412,    200,    168,    38,     38,    134,    134,
	// 8 - 15
	100,    100,    100,    100,    68,     68,     68,     68
    };

    // 
    static short twoBitBlack[] = {292, 260, 226, 226};   // 0 - 3

    // Main black run table, using the last 9 bits of possible 13 bit code
    static short black[] = {
	// 0 - 7
	62,     62,     30,     30,     0,      0,      0,      0, 
	// 8 - 15
	0,      0,      0,      0,      0,      0,      0,      0, 
	// 16 - 23
	0,      0,      0,      0,      0,      0,      0,      0, 
	// 24 - 31
	0,      0,      0,      0,      0,      0,      0,      0, 
	// 32 - 39
	3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225, 
	// 40 - 47
	3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225, 
	// 48 - 55
	3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225, 
	// 56 - 63
	3225,   3225,   3225,   3225,   3225,   3225,   3225,   3225, 
	// 64 - 71
	588,    588,    588,    588,    588,    588,    588,    588, 
	// 72 - 79
	1680,   1680,  20499,  22547,  24595,  26643,   1776,   1776, 
	// 80 - 87
	1808,   1808, -24557, -22509, -20461, -18413,   1904,   1904, 
	// 88 - 95
	1936,   1936, -16365, -14317,    782,    782,    782,    782, 
	// 96 - 103
	814,    814,    814,    814, -12269, -10221,  10257,  10257, 
	// 104 - 111
	12305,  12305,  14353,  14353,  16403,  18451,   1712,   1712, 
	// 112 - 119
	1744,   1744,  28691,  30739, -32749, -30701, -28653, -26605, 
	// 120 - 127
	2061,   2061,   2061,   2061,   2061,   2061,   2061,   2061, 
	// 128 - 135
	424,    424,    424,    424,    424,    424,    424,    424, 
	// 136 - 143
	424,    424,    424,    424,    424,    424,    424,    424, 
	// 144 - 151
	424,    424,    424,    424,    424,    424,    424,    424, 
	// 152 - 159
	424,    424,    424,    424,    424,    424,    424,    424, 
	// 160 - 167
	750,    750,    750,    750,   1616,   1616,   1648,   1648, 
	// 168 - 175
	1424,   1424,   1456,   1456,   1488,   1488,   1520,   1520, 
	// 176 - 183
	1840,   1840,   1872,   1872,   1968,   1968,   8209,   8209, 
	// 184 - 191
	524,    524,    524,    524,    524,    524,    524,    524, 
	// 192 - 199
	556,    556,    556,    556,    556,    556,    556,    556, 
	// 200 - 207
	1552,   1552,   1584,   1584,   2000,   2000,   2032,   2032, 
	// 208 - 215
	976,    976,   1008,   1008,   1040,   1040,   1072,   1072, 
	// 216 - 223
	1296,   1296,   1328,   1328,    718,    718,    718,    718, 
	// 224 - 231
	456,    456,    456,    456,    456,    456,    456,    456, 
	// 232 - 239
	456,    456,    456,    456,    456,    456,    456,    456, 
	// 240 - 247
	456,    456,    456,    456,    456,    456,    456,    456, 
	// 248 - 255
	456,    456,    456,    456,    456,    456,    456,    456, 
	// 256 - 263
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 264 - 271
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 272 - 279
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 280 - 287
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 288 - 295
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 296 - 303
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 304 - 311
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 312 - 319
	326,    326,    326,    326,    326,    326,    326,    326, 
	// 320 - 327
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 328 - 335
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 336 - 343
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 344 - 351
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 352 - 359
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 360 - 367
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 368 - 375
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 376 - 383
	358,    358,    358,    358,    358,    358,    358,    358, 
	// 384 - 391
	490,    490,    490,    490,    490,    490,    490,    490, 
	// 392 - 399
	490,    490,    490,    490,    490,    490,    490,    490, 
	// 400 - 407
	4113,   4113,   6161,   6161,    848,    848,    880,    880, 
	// 408 - 415
	912,    912,    944,    944,    622,    622,    622,    622, 
	// 416 - 423
	654,    654,    654,    654,   1104,   1104,   1136,   1136, 
	// 424 - 431
	1168,   1168,   1200,   1200,   1232,   1232,   1264,   1264, 
	// 432 - 439
	686,    686,    686,    686,   1360,   1360,   1392,   1392, 
	// 440 - 447
	12,     12,     12,     12,     12,     12,     12,     12, 
	// 448 - 455
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 456 - 463
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 464 - 471
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 472 - 479
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 480 - 487
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 488 - 495
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 496 - 503
	390,    390,    390,    390,    390,    390,    390,    390, 
	// 504 - 511
	390,    390,    390,    390,    390,    390,    390,    390, 
    };

    static byte twoDCodes[] = {
	// 0 - 7
	80,     88,     23,     71,     30,     30,     62,     62, 
	// 8 - 15
	4,      4,      4,      4,      4,      4,      4,      4, 
	// 16 - 23
	11,     11,     11,     11,     11,     11,     11,     11, 
	// 24 - 31
	11,     11,     11,     11,     11,     11,     11,     11, 
	// 32 - 39
	35,     35,     35,     35,     35,     35,     35,     35, 
	// 40 - 47
	35,     35,     35,     35,     35,     35,     35,     35, 
	// 48 - 55
	51,     51,     51,     51,     51,     51,     51,     51, 
	// 56 - 63
	51,     51,     51,     51,     51,     51,     51,     51, 
	// 64 - 71
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 72 - 79
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 80 - 87
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 88 - 95
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 96 - 103
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 104 - 111
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 112 - 119
	41,     41,     41,     41,     41,     41,     41,     41, 
	// 120 - 127
	41,     41,     41,     41,     41,     41,     41,     41, 
    };

    /**
     * @param fillOrder   The fill order of the compressed data bytes.
     */
    public TIFFFaxDecoder(int fillOrder, int w, int h) {
	this.fillOrder = fillOrder;
	this.w = w;
	this.h = h;

	this.bitPointer = 0;
	this.bytePointer = 0;
	this.prevChangingElems = new int[w];
	this.currChangingElems = new int[w];
    }

    // One-dimensional decoding methods

    public void decode1D(byte[] buffer, byte[] compData,
                         int startX, int height) {
	this.data = compData;

        int lineOffset = 0;
        int scanlineStride = (w + 7)/8;

	bitPointer = 0;
	bytePointer = 0;
	
	for (int i = 0; i < height; i++) {
	    decodeNextScanline(buffer, lineOffset, startX);
            lineOffset += scanlineStride;
	}
    }

    public void decodeNextScanline(byte[] buffer,
                                   int lineOffset, int bitOffset) {
	int bits = 0, code = 0, isT = 0;
	int current, entry, twoBits;
	boolean isWhite = true;

	// Initialize starting of the changing elements array
	changingElemSize = 0;

	// While scanline not complete
	while (bitOffset < w) {
	    while (isWhite) {
		// White run
		current = nextNBits(10);
		entry = white[current];
		
		// Get the 3 fields from the entry
		isT = entry & 0x0001;
		bits = (entry >>> 1) & 0x0f;
		
		if (bits == 12) {          // Additional Make up code
		    // Get the next 2 bits
		    twoBits = nextLesserThan8Bits(2);
		    // Consolidate the 2 new bits and last 2 bits into 4 bits
		    current = ((current << 2) & 0x000c) | twoBits; 
		    entry = additionalMakeup[current];
		    bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
		    code  = (entry >>> 4) & 0x0fff;  // 12 bits
                    bitOffset += code; // Skip white run

		    updatePointer(4 - bits);
		} else if (bits == 0) {     // ERROR
		    throw new Error("TIFFFaxDecoder0");
		} else if (bits == 15) {    // EOL
		    throw new Error("TIFFFaxDecoder1");
		} else {
		    // 11 bits - 0000 0111 1111 1111 = 0x07ff
		    code = (entry >>> 5) & 0x07ff;  
                    bitOffset += code;

		    updatePointer(10 - bits);
		    if (isT == 0) {
			isWhite = false;
			currChangingElems[changingElemSize++] = bitOffset;
		    }
		}
	    }

	    // Check whether this run completed one width, if so 
	    // advance to next byte boundary for compression = 2.
	    if (bitOffset == w) {
		if (compression == 2) {		
		    advancePointer();
		}
		break;
	    }

	    while (isWhite == false) {
		// Black run
		current = nextLesserThan8Bits(4);
		entry = initBlack[current];
		
		// Get the 3 fields from the entry
		isT = entry & 0x0001;
		bits = (entry >>> 1) & 0x000f;
		code = (entry >>> 5) & 0x07ff;

		if (code == 100) {
		    current = nextNBits(9);
		    entry = black[current];
		    
		    // Get the 3 fields from the entry
		    isT = entry & 0x0001;
		    bits = (entry >>> 1) & 0x000f;
		    code = (entry >>> 5) & 0x07ff;

		    if (bits == 12) {
			// Additional makeup codes
			updatePointer(5);
			current = nextLesserThan8Bits(4);
			entry = additionalMakeup[current];
			bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
			code  = (entry >>> 4) & 0x0fff;  // 12 bits

                        setToBlack(buffer, lineOffset, bitOffset, code);
                        bitOffset += code;

			updatePointer(4 - bits);
		    } else if (bits == 15) {
			// EOL code
			throw new Error("TIFFFaxDecoder2");
		    } else {
                        setToBlack(buffer, lineOffset, bitOffset, code);
                        bitOffset += code;

			updatePointer(9 - bits);
			if (isT == 0) {
			    isWhite = true;
			    currChangingElems[changingElemSize++] = bitOffset;
			}
		    }
		} else if (code == 200) {
		    // Is a Terminating code
		    current = nextLesserThan8Bits(2);
		    entry = twoBitBlack[current];
		    code = (entry >>> 5) & 0x07ff;
		    bits = (entry >>> 1) & 0x0f;

                    setToBlack(buffer, lineOffset, bitOffset, code);
                    bitOffset += code;

		    updatePointer(2 - bits);
		    isWhite = true;
		    currChangingElems[changingElemSize++] = bitOffset;
		} else {
		    // Is a Terminating code
                    setToBlack(buffer, lineOffset, bitOffset, code);
                    bitOffset += code;

		    updatePointer(4 - bits);
		    isWhite = true;
		    currChangingElems[changingElemSize++] = bitOffset;
		}
	    }

	    // Check whether this run completed one width
	    if (bitOffset == w) {
		if (compression == 2) {
		    advancePointer();
		}
		break;
	    }
	}

	currChangingElems[changingElemSize++] = bitOffset;
    }

    // Two-dimensional decoding methods

    public void decode2D(byte[] buffer,
                         byte compData[],
                         int startX,
                         int height,
                         long tiffT4Options) {
	this.data = compData;
	compression = 3;

	bitPointer = 0;
	bytePointer = 0;

        int scanlineStride = (w + 7)/8;

	int a0, a1, b1, b2;
        int[] b = new int[2];
	int entry, code, bits;
	boolean isWhite;
	int currIndex = 0;
	int temp[];
	
	// fillBits - dealt with this in readEOL
	// 1D/2D encoding - dealt with this in readEOL

	// uncompressedMode - haven't dealt with this yet.
	

	oneD = (int)(tiffT4Options & 0x01);
	uncompressedMode = (int)((tiffT4Options & 0x02) >> 1);
	fillBits = (int)((tiffT4Options & 0x04) >> 2);

	// The data must start with an EOL code
	if (readEOL() != 1) {
	    throw new Error("TIFFFaxDecoder3");
	}

        int lineOffset = 0;
        int bitOffset;

	// Then the 1D encoded scanline data will occur, changing elements
	// array gets set.
	decodeNextScanline(buffer, lineOffset, startX);
        lineOffset += scanlineStride;

	for (int lines = 1; lines < height; lines++) {

            // Every line must begin with an EOL followed by a bit which
            // indicates whether the following scanline is 1D or 2D encoded.
	    if (readEOL() == 0) {
		// 2D encoded scanline follows		
		
		// Initialize previous scanlines changing elements, and 
		// initialize current scanline's changing elements array
		temp = prevChangingElems;
		prevChangingElems = currChangingElems;
		currChangingElems = temp;
		currIndex = 0;
                
		// a0 has to be set just before the start of this scanline.
		a0 = -1;
		isWhite = true;
		bitOffset = startX;

                lastChangingElement = 0;

		while (bitOffset < w) {
		    // Get the next changing element
		    getNextChangingElement(a0, isWhite, b);
		    
		    b1 = b[0];
		    b2 = b[1];
                    
		    // Get the next seven bits
		    entry = nextLesserThan8Bits(7);
                    
		    // Run these through the 2DCodes table
		    entry = (int)(twoDCodes[entry] & 0xff);
                    
		    // Get the code and the number of bits used up
		    code = (entry & 0x78) >>> 3;
		    bits = entry & 0x07;
                    
		    if (code == 0) {
                        if (!isWhite) {
                            setToBlack(buffer, lineOffset, bitOffset,
                                       b2 - bitOffset);
                        }
			bitOffset = a0 = b2;
                        
			// Set pointer to consume the correct number of bits.
			updatePointer(7 - bits);
		    } else if (code == 1) {
			// Horizontal
			updatePointer(7 - bits);
                        
			// identify the next 2 codes.
			int number;
			if (isWhite) {
			    number = decodeWhiteCodeWord();
                            bitOffset += number;
			    currChangingElems[currIndex++] = bitOffset;
                            
			    number = decodeBlackCodeWord();
                            setToBlack(buffer, lineOffset, bitOffset, number);
			    bitOffset += number;
			    currChangingElems[currIndex++] = bitOffset;
			} else {
			    number = decodeBlackCodeWord();
                            setToBlack(buffer, lineOffset, bitOffset, number);
                            bitOffset += number;
			    currChangingElems[currIndex++] = bitOffset;
                            
			    number = decodeWhiteCodeWord();
			    bitOffset += number;
			    currChangingElems[currIndex++] = bitOffset;
			}
                        
			a0 = bitOffset;
		    } else if (code <= 8) {
			// Vertical
			a1 = b1 + (code - 5);
                        
			currChangingElems[currIndex++] = a1;
                        
			// We write the current color till a1 - 1 pos,
			// since a1 is where the next color starts
                        if (!isWhite) {
                            setToBlack(buffer, lineOffset, bitOffset, 
                                       a1 - bitOffset);
                        }
                        bitOffset = a0 = a1;
                        isWhite = !isWhite;
                            
                        updatePointer(7 - bits);
		    } else {
			throw new Error("TIFFFaxDecoder4");
		    }
		}
                
		// Add the changing element beyond the current scanline for the
		// other color too
		currChangingElems[currIndex++] = bitOffset;
		changingElemSize = currIndex;
	    } else {
		// 1D encoded scanline follows
		decodeNextScanline(buffer, lineOffset, startX);
	    }

            lineOffset += scanlineStride;
        }
    }

    public synchronized void decodeT6(byte[] buffer,
                                      byte[] compData,
                                      int startX,
                                      int height,
                                      long tiffT6Options) {
	this.data = compData;
	compression = 4;

	bitPointer = 0;
	bytePointer = 0;

        int scanlineStride = (w + 7)/8;

	int a0, a1, b1, b2;
	int entry, code, bits;
	boolean isWhite;
	int currIndex;
	int temp[];

        // Return values from getNextChangingElement
        int[] b = new int[2];
	
	// uncompressedMode - have written some code for this, but this 
	// has not been tested due to lack of test images using this optional
	
	uncompressedMode = (int)((tiffT6Options & 0x02) >> 1);

        // Local cached reference
        int[] cce = currChangingElems;

	// Assume invisible preceding row of all white pixels and insert
	// both black and white changing elements beyond the end of this
	// imaginary scanline.
	changingElemSize = 0;
	cce[changingElemSize++] = w;
	cce[changingElemSize++] = w;

        int lineOffset = 0;
        int bitOffset;

	for (int lines = 0; lines < height; lines++) {
	    // a0 has to be set just before the start of the scanline.
	    a0 = -1;
	    isWhite = true;
	
	    // Assign the changing elements of the previous scanline to 
	    // prevChangingElems and start putting this new scanline's
	    // changing elements into the currChangingElems.
	    temp = prevChangingElems;
	    prevChangingElems = currChangingElems;
	    cce = currChangingElems = temp;
	    currIndex = 0;

	    // Start decoding the scanline at startX in the raster
            bitOffset = startX;

            // Reset search start position for getNextChangingElement
            lastChangingElement = 0;

	    // Till one whole scanline is decoded
	    while (bitOffset < w) {
		// Get the next changing element 
                getNextChangingElement(a0, isWhite, b);
		b1 = b[0];
		b2 = b[1];

		// Get the next seven bits
		entry = nextLesserThan8Bits(7);
		// Run these through the 2DCodes table
		entry = (int)(twoDCodes[entry] & 0xff);

		// Get the code and the number of bits used up
		code = (entry & 0x78) >>> 3;
		bits = entry & 0x07;
                
		if (code == 0) { // Pass
                    // We always assume WhiteIsZero format for fax.
                    if (!isWhite) {
                        setToBlack(buffer, lineOffset, bitOffset, 
                                   b2 - bitOffset);
                    }
                    bitOffset = a0 = b2;

		    // Set pointer to only consume the correct number of bits.
		    updatePointer(7 - bits);
		} else if (code == 1) { // Horizontal
		    // Set pointer to only consume the correct number of bits.
		    updatePointer(7 - bits);
		    
		    // identify the next 2 alternating color codes.
		    int number;
		    if (isWhite) {
			// Following are white and black runs
			number = decodeWhiteCodeWord();
                        bitOffset += number;
			cce[currIndex++] = bitOffset;

			number = decodeBlackCodeWord();
                        setToBlack(buffer, lineOffset, bitOffset, number);
                        bitOffset += number;
			cce[currIndex++] = bitOffset;
		    } else {
			// First a black run and then a white run follows
			number = decodeBlackCodeWord();
                        setToBlack(buffer, lineOffset, bitOffset, number);
                        bitOffset += number;
			cce[currIndex++] = bitOffset;

			number = decodeWhiteCodeWord();
                        bitOffset += number;
			cce[currIndex++] = bitOffset;
		    }
		    
		    a0 = bitOffset;
		} else if (code <= 8) { // Vertical
		    a1 = b1 + (code - 5);
		    cce[currIndex++] = a1;

		    // We write the current color till a1 - 1 pos,
		    // since a1 is where the next color starts
                    if (!isWhite) {
                        setToBlack(buffer, lineOffset, bitOffset,
                                   a1 - bitOffset);
                    }
                    bitOffset = a0 = a1;
                    isWhite = !isWhite;

		    updatePointer(7 - bits);
		} else if (code == 11) {
		    if (nextLesserThan8Bits(3) != 7) {
			throw new Error("TIFFFaxDecoder5");
		    }

		    int zeros = 0;
		    boolean exit = false;

		    while (!exit) {
			while (nextLesserThan8Bits(1) != 1) {
			    zeros++;
			}
			
			if (zeros > 5) {
			    // Exit code
			    
			    // Zeros before exit code
			    zeros = zeros - 6;

			    if (!isWhite && (zeros > 0)) {
				cce[currIndex++] = bitOffset;
			    }
			    
			    // Zeros before the exit code
                            bitOffset += zeros;
			    if (zeros > 0) {
				// Some zeros have been written
				isWhite = true;
			    } 
                            
			    // Read in the bit which specifies the color of
			    // the following run
			    if (nextLesserThan8Bits(1) == 0) {
				if (!isWhite) {
				    cce[currIndex++] = bitOffset;
				}
				isWhite = true;
			    } else {
				if (isWhite) {
				    cce[currIndex++] = bitOffset;
				}
				isWhite = false;
			    }

			    exit = true;
			} 

                        if (zeros == 5) {
			    if (!isWhite) {
			        cce[currIndex++] = bitOffset;
			    }
                            bitOffset += zeros;

			    // Last thing written was white
			    isWhite = true;
			} else {
                            bitOffset += zeros;

			    cce[currIndex++] = bitOffset;
                            setToBlack(buffer, lineOffset, bitOffset, 1);
                            ++bitOffset;

			    // Last thing written was black
			    isWhite = false;
			}

		    }
		} else {
		    throw new Error("TIFFFaxDecoder5");
		}
	    }
	    
	    // Add the changing element beyond the current scanline for the
	    // other color too
	    cce[currIndex++] = bitOffset;

	    // Number of changing elements in this scanline.
	    changingElemSize = currIndex;

            lineOffset += scanlineStride;
	}
    }

    private void setToBlack(byte[] buffer,
                            int lineOffset, int bitOffset,
                            int numBits) {
        int bitNum = 8*lineOffset + bitOffset;
        int lastBit = bitNum + numBits;

        int byteNum = bitNum >> 3;

        // Handle bits in first byte
        int shift = bitNum & 0x7;
        if (shift > 0) {
            int maskVal = 1 << (7 - shift);
            byte val = buffer[byteNum];
            while (maskVal > 0 && bitNum < lastBit) {
                val |= maskVal;
                maskVal >>= 1;
                ++bitNum;
            }
            buffer[byteNum] = val;
        }

        // Fill in 8 bits at a time
        byteNum = bitNum >> 3;
        while (bitNum < lastBit - 7) {
            buffer[byteNum++] = (byte)255;
            bitNum += 8;
        }

        // Fill in remaining bits
        while (bitNum < lastBit) {
            byteNum = bitNum >> 3;
            buffer[byteNum] |= 1 << (7 - (bitNum & 0x7));
            ++bitNum;
        }
    }

    // Returns run length
    private int decodeWhiteCodeWord() {
	int current, entry, bits, isT, twoBits, code = -1;
        int runLength = 0;
	boolean isWhite = true;

	while (isWhite) {
	    current = nextNBits(10);
	    entry = white[current];
	    
	    // Get the 3 fields from the entry
	    isT = entry & 0x0001;
	    bits = (entry >>> 1) & 0x0f;
	    
	    if (bits == 12) {           // Additional Make up code
		// Get the next 2 bits
		twoBits = nextLesserThan8Bits(2);
		// Consolidate the 2 new bits and last 2 bits into 4 bits
		current = ((current << 2) & 0x000c) | twoBits; 
		entry = additionalMakeup[current];
		bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
		code = (entry >>> 4) & 0x0fff;   // 12 bits
                runLength += code;
		updatePointer(4 - bits);
	    } else if (bits == 0) {     // ERROR
		throw new Error("TIFFFaxDecoder0");
	    } else if (bits == 15) {    // EOL
		throw new Error("TIFFFaxDecoder1");
	    } else {
		// 11 bits - 0000 0111 1111 1111 = 0x07ff
		code = (entry >>> 5) & 0x07ff;  
                runLength += code;
		updatePointer(10 - bits);
		if (isT == 0) {
		    isWhite = false;
		}
	    }
	}

	return runLength;
    }

    // Returns run length
    private int decodeBlackCodeWord() {
	int current, entry, bits, isT, code = -1;
        int runLength = 0;
	boolean isWhite = false;
	
	while (!isWhite) {
	    current = nextLesserThan8Bits(4);
	    entry = initBlack[current];
	    
	    // Get the 3 fields from the entry
	    isT = entry & 0x0001;
	    bits = (entry >>> 1) & 0x000f;
	    code = (entry >>> 5) & 0x07ff;
	    
	    if (code == 100) {
		current = nextNBits(9);
		entry = black[current];
		
		// Get the 3 fields from the entry
		isT = entry & 0x0001;
		bits = (entry >>> 1) & 0x000f;
		code = (entry >>> 5) & 0x07ff;
		
		if (bits == 12) {
		    // Additional makeup codes		    
		    updatePointer(5);
		    current = nextLesserThan8Bits(4);
		    entry = additionalMakeup[current];
		    bits = (entry >>> 1) & 0x07;     // 3 bits 0000 0111
		    code  = (entry >>> 4) & 0x0fff;  // 12 bits
                    runLength += code;
		    
		    updatePointer(4 - bits);
		} else if (bits == 15) {
		    // EOL code
		    throw new Error("TIFFFaxDecoder2");
		} else {
                    runLength += code;
		    updatePointer(9 - bits);
		    if (isT == 0) {
			isWhite = true;
		    }
		}
	    } else if (code == 200) {
		// Is a Terminating code
		current = nextLesserThan8Bits(2);
		entry = twoBitBlack[current];
		code = (entry >>> 5) & 0x07ff;
                runLength += code;
		bits = (entry >>> 1) & 0x0f;
		updatePointer(2 - bits);
		isWhite = true;
	    } else {
		// Is a Terminating code
                runLength += code;
		updatePointer(4 - bits);
		isWhite = true;
	    }
	}

	return runLength;
    }

    private int readEOL() {
	if (fillBits == 0) {
	    if (nextNBits(12) != 1) {
		throw new Error("TIFFFaxDecoder6");
	    }
	} else if (fillBits == 1) {

	    // First EOL code word xxxx 0000 0000 0001 will occur
	    // As many fill bits will be present as required to make
	    // the EOL code of 12 bits end on a byte boundary.

	    int bitsLeft = 8 - bitPointer;

	    if (nextNBits(bitsLeft) != 0) {
		    throw new Error("TIFFFaxDecoder8");
	    }

	    // If the number of bitsLeft is less than 8, then to have a 12
	    // bit EOL sequence, two more bytes are certainly going to be
	    // required. The first of them has to be all zeros, so ensure 
	    // that.
	    if (bitsLeft < 4) {
		if (nextNBits(8) != 0) {
		    throw new Error("TIFFFaxDecoder8");
		}
	    }

	    // There might be a random number of fill bytes with 0s, so 
	    // loop till the EOL of 0000 0001 is found, as long as all
	    // the bytes preceding it are 0's.
	    int n;
	    while ((n = nextNBits(8)) != 1) {
		
		// If not all zeros
		if (n != 0) {
		    throw new Error("TIFFFaxDecoder8");
		}
	    }
	}

	// If one dimensional encoding mode, then always return 1 
	if (oneD == 0) {
	    return 1;
	} else {
	    // Otherwise for 2D encoding mode,
	    // The next one bit signifies 1D/2D encoding of next line.
	    return nextLesserThan8Bits(1);	    	    
	}
    }

    private void getNextChangingElement(int a0, boolean isWhite, int[] ret) {
        // Local copies of instance variables
        int[] pce = this.prevChangingElems;
        int ces = this.changingElemSize;

        // If the previous match was at an odd element, we still
        // have to search the preceeding element.
        // int start = lastChangingElement & ~0x1;
        int start = lastChangingElement > 0 ? lastChangingElement - 1 : 0;
        if (isWhite) {
            start &= ~0x1; // Search even numbered elements
        } else {
            start |= 0x1; // Search odd numbered elements
        }

        int i = start;
        for (; i < ces; i += 2) {
            int temp = pce[i];
            if (temp > a0) {
                lastChangingElement = i;
                ret[0] = temp;
                break;
            }
        }

        if (i + 1 < ces) {
            ret[1] = pce[i + 1];
        }
    }

    private int nextNBits(int bitsToGet) {
	byte b, next, next2next;
	int l = data.length - 1;
        int bp = this.bytePointer;
	    
	if (fillOrder == 1) {
	    b = data[bp];
	    
	    if (bp == l) {
		next = 0x00;
		next2next = 0x00;
	    } else if ((bp + 1) == l) {
		next = data[bp + 1];
		next2next = 0x00;
	    } else {
		next = data[bp + 1];
		next2next = data[bp + 2];
	    }
	} else if (fillOrder == 2) {
	    b = flipTable[data[bp] & 0xff];

	    if (bp == l) {
		next = 0x00;
		next2next = 0x00;
	    } else if ((bp + 1) == l) {
		next = flipTable[data[bp + 1] & 0xff];
		next2next = 0x00;
	    } else {
		next = flipTable[data[bp + 1] & 0xff];
		next2next = flipTable[data[bp + 2] & 0xff];
	    }
	} else {
	    throw new Error("TIFFFaxDecoder7");
	}

	int bitsLeft = 8 - bitPointer;
	int bitsFromNextByte = bitsToGet - bitsLeft;
	int bitsFromNext2NextByte = 0;
	if (bitsFromNextByte > 8) {
	    bitsFromNext2NextByte = bitsFromNextByte - 8;
	    bitsFromNextByte = 8;
	}
	
	bytePointer++;
	
	int i1 = (b & table1[bitsLeft]) << (bitsToGet - bitsLeft);
	int i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte);
	
	int i3 = 0;
	if (bitsFromNext2NextByte != 0) {
	    i2 <<= bitsFromNext2NextByte;
	    i3 = (next2next & table2[bitsFromNext2NextByte]) >>> 
		(8 - bitsFromNext2NextByte);
	    i2 |= i3;
	    bytePointer++;
	    bitPointer = bitsFromNext2NextByte;
	} else {
	    if (bitsFromNextByte == 8) {
		bitPointer = 0;
		bytePointer++;
	    } else {
		bitPointer = bitsFromNextByte;
	    }
	}
	
	int i = i1 | i2;
	return i;
    }

    private int nextLesserThan8Bits(int bitsToGet) {
	byte b, next;
	int l = data.length - 1;
        int bp = this.bytePointer;

	if (fillOrder == 1) {
	    b = data[bp];
	    if (bp == l) {
		next = 0x00;
	    } else {
		next = data[bp + 1];
	    }
	} else if (fillOrder == 2) {
	    b = flipTable[data[bp] & 0xff];
	    if (bp == l) {
		next = 0x00;
	    } else {
		next = flipTable[data[bp + 1] & 0xff];
	    }
	} else {
	    throw new Error("TIFFFaxDecoder7");
	}

	int bitsLeft = 8 - bitPointer;
	int bitsFromNextByte = bitsToGet - bitsLeft;

	int shift = bitsLeft - bitsToGet;
	int i1, i2;
	if (shift >= 0) {
	    i1 = (b & table1[bitsLeft]) >>> shift;
	    bitPointer += bitsToGet;
	    if (bitPointer == 8) {
		bitPointer = 0;
		bytePointer++;
	    }
	} else {
	    i1 = (b & table1[bitsLeft]) << (-shift);
	    i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte);

	    i1 |= i2;
	    bytePointer++;
	    bitPointer = bitsFromNextByte;
	}

	return i1;
    }

    // Move pointer backwards by given amount of bits
    private void updatePointer(int bitsToMoveBack) {
	int i = bitPointer - bitsToMoveBack;
	
	if (i < 0) {
	    bytePointer--;
	    bitPointer = 8 + i;
	} else {
	    bitPointer = i;
	}
    }
    
    // Move to the next byte boundary
    private boolean advancePointer() {
	if (bitPointer != 0) {
	    bytePointer++;
	    bitPointer = 0;
	}
	
	return true;
    }
}

